#include "utils/socket.h"
#include <iostream>
#include <vector>
#include <memory>

using namespace cox;

// 组播地址(224.0.0.0-239.255.255.255范围内）
const std::string    MULTICAST_GROUP = "224.2.2.4";
const unsigned short UNICAST_PORT    = 9001; // 普通UDP端口
const unsigned short MULTICAST_PORT  = 9002; // 组播端口

/// @brief UDP服务(兼容单播&组播)
void testUdpServer() {
	// 1. 创建普通UDP socket(处理单播消息）
	std::unique_ptr<Socket> unicastSock(new Socket(Socket::UDP));
	if (!unicastSock->isValid()) {
		std::cerr << "创建普通UDP socket失败" << std::endl;
		return;
	}
	// 绑定普通UDP端口
	NetAddr unicastAddr("0.0.0.0", UNICAST_PORT);
	if (!unicastSock->bind(unicastAddr)) {
		std::cerr << "绑定普通UDP端口失败，错误码：" << unicastSock->getError() << std::endl;
		return;
	}

	// 2. 创建组播UDP socket(处理组播消息）
	std::unique_ptr<Socket> multicastSock(new Socket(Socket::UDP));
	if (!multicastSock->isValid()) {
		std::cerr << "创建组播UDP socket失败" << std::endl;
		return;
	}
	// 绑定组播端口(必须绑定才能接收组播消息）
	NetAddr multicastAddr("0.0.0.0", MULTICAST_PORT);
	if (!multicastSock->bind(multicastAddr)) {
		std::cerr << "绑定组播端口失败，错误码：" << multicastSock->getError() << std::endl;
		return;
	}
	// 加入组播组(本地IP填0.0.0.0自动选择网卡）
	if (!multicastSock->addMemberShip(MULTICAST_GROUP, "0.0.0.0")) {
		std::cerr << "加入组播组失败，错误码：" << multicastSock->getError() << std::endl;
		return;
	}

	std::cout << "UDP服务(单播&组播)启动：" << std::endl;
	std::cout << "  - 普通UDP监听：0.0.0.0:" << UNICAST_PORT << std::endl;
	std::cout << "  - 组播UDP监听：" << MULTICAST_GROUP << ":" << MULTICAST_PORT << std::endl;

	// 管理需要监听的socket(普通UDP + 组播UDP）
	std::vector<Socket *> readVec;

	while (true) {
		readVec.clear();
		readVec.push_back(unicastSock.get());   // 加入普通UDP socket
		readVec.push_back(multicastSock.get()); // 加入组播UDP socket

		// 等待可读事件(超时5秒，循环检查）
		int ret = Socket::select(&readVec, nullptr, nullptr, TimeVal(5, 0));
		if (ret <= 0) {
			continue;
		}

		// 处理就绪的socket
		for (Socket *sock: readVec) {
			char      buf[1024] = {0};
			NetAddr   senderAddr; // 发送方地址
			long long recvLen = sock->recvfrom(buf, 1023, senderAddr);

			if (recvLen <= 0) {
				std::cerr << "接收数据失败，错误码：" << sock->getError() << std::endl;
				continue;
			}

			// 区分是普通UDP还是组播消息
			if (sock == unicastSock.get()) {
				std::cout << "单播消息 (来自" << senderAddr.host << ":" << senderAddr.port << ") : " << buf << std::endl;
				std::string reply = "单播已收到：" + std::string(buf);
				sock->sendto(reply.c_str(), reply.size(), senderAddr);
			} else if (sock == multicastSock.get()) {
				std::cout << "组播消息 (来自" << senderAddr.host << ":" << senderAddr.port << ") : " << buf << std::endl;
				std::string reply = "组播已收到：" + std::string(buf);
				sock->sendto(reply.c_str(), reply.size(), senderAddr);
			}
		}
	}
}

// 编译：g++ -std=c++11 -o udp_server udp_server.cpp SocketAdapter.cpp TimeAdapter.cpp
// echo "单播消息" | nc -u -w 1 127.0.0.1 9001
// echo "组播消息" | nc -u -w 1 224.2.2.4 9002
int main() {
	testUdpServer();
	return 0;
}
